package br.com.bancodecurriculos.pessoa.comum.dao.impl;

import java.io.IOException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import br.com.bancodecurriculos.pessoa.comum.dao.ITelefoneDAOHelper;
import br.com.bancodecurriculos.pessoa.comum.dominio.Telefone;
import br.com.bancodecurriculos.pessoa.comum.dominio.Telefone.TipoTelefone;
import br.com.bancodecurriculos.util.dao.JDBCConnectionFactory;
import br.com.bancodecurriculos.util.exception.RegistroExistenteException;
import br.com.bancodecurriculos.util.exception.RegistroInexistenteException;

public class TelefoneDAOHelper implements ITelefoneDAOHelper {

	private static final String SQL_TIPO_TELEFONE_GET_BY_NAME = "SELECT * FROM tipotelefone WHERE nome = ?";
	private static final String SQL_TIPO_TELEFONE_GET_ALL = "SELECT * FROM tipotelefone";

	private static final String SQL_TELEFONE_INSERT = "INSERT INTO telefone (pais, area, numero, id_tipotelefone, id_pessoa)"
			+ " values (?, ?, ?, ?. ?)";
	private static final String SQL_TELEFONE_UPDATE = "UPDATE telefone SET pais = ?, area = ?, numero = ?, id_tipotelefone WHERE id = ?";
	private static final String SQL_TELEFONE_GET_BY_PAIS_AREA_NUMERO = "SELECT id FROM telefone WHERE pais = ? AND area = ? AND numero = ?";
	private static final String SQL_TELEFONE_GET_BY_ID = "SELECT telefone.id AS id, telefone.pais AS pais, telefone.area AS area,"
			+ " telefone.numero AS numero, telefone.id_tipotelefone AS id_tipotelefone, tipotelefone.nome AS nome_tipotelefone FROM telefone"
			+ " INNER JOIN tipotelefone ON telefone.id_tipotelefone = tipotelefone.id WHERE telefone.id = ?";
	private static final String SQL_TELEFONE_GET_BY_ID_PESSOA = "SELECT telefone.id AS id, telefone.pais AS pais, telefone.area AS area,"
			+ " telefone.numero AS numero, telefone.id_tipotelefone AS id_tipotelefone, tipotelefone.nome AS nome_tipotelefone FROM telefone"
			+ " INNER JOIN tipotelefone ON telefone.id_tipotelefone = tipotelefone.id WHERE telefone.id_pessoa = ?";
	private static final String SQL_TELEFONE_DELETE = "DELETE FROM telefone WHERE id = ?";

	private static final String TELEFONE_EXISTENTE_EXCEPTION = "Telefone j� existe!";
	private static final String TELEFONE_INEXISTENTE_EXCEPTION = "Telefone inexistente!";

	@Deprecated
	@Override
	public void save(Telefone t) throws ClassNotFoundException, SQLException,
			RegistroExistenteException, IOException {
		// TODO Auto-generated method stub

	}

	@Override
	public void save(Telefone t, long idPessoa) throws ClassNotFoundException,
			SQLException, RegistroExistenteException, IOException {
		if (this.getByPaisAreaNumero(t.getPais(), t.getArea(), t.getNumero()) == null) {
			TipoTelefone tipoTelefone = this.getTipoTelefoneByName(t
					.getTipoTelefone().getNome());
			PreparedStatement preparedStatement = JDBCConnectionFactory
					.getInstance().getConnection()
					.prepareStatement(SQL_TELEFONE_INSERT);
			preparedStatement.setInt(1, t.getPais());
			preparedStatement.setInt(2, t.getArea());
			preparedStatement.setInt(3, t.getNumero());
			preparedStatement.setLong(4, tipoTelefone.getId());
			preparedStatement.setLong(5, idPessoa);
			preparedStatement.executeUpdate();
			preparedStatement.close();
		} else {
			throw new RegistroExistenteException(TELEFONE_EXISTENTE_EXCEPTION);
		}
	}

	@Override
	public void update(Telefone t) throws ClassNotFoundException, SQLException,
			RegistroInexistenteException, IOException {
		if (this.getByPaisAreaNumero(t.getPais(), t.getArea(), t.getNumero()) != null) {
			TipoTelefone tipoTelefone = this.getTipoTelefoneByName(t
					.getTipoTelefone().getNome());
			PreparedStatement preparedStatement = JDBCConnectionFactory
					.getInstance().getConnection()
					.prepareStatement(SQL_TELEFONE_UPDATE);
			preparedStatement.setInt(1, t.getPais());
			preparedStatement.setInt(2, t.getArea());
			preparedStatement.setInt(3, t.getNumero());
			preparedStatement.setLong(4, tipoTelefone.getId());
			preparedStatement.setLong(5, t.getId());
			preparedStatement.executeUpdate();
			preparedStatement.close();
		} else {
			throw new RegistroInexistenteException(
					TELEFONE_INEXISTENTE_EXCEPTION);
		}
	}

	@Override
	public Telefone getById(Long id) throws ClassNotFoundException,
			SQLException, IOException {
		PreparedStatement preparedStatement = JDBCConnectionFactory
				.getInstance().getConnection()
				.prepareStatement(SQL_TELEFONE_GET_BY_ID);
		preparedStatement.setLong(1, id);
		ResultSet resultSet = preparedStatement.executeQuery();
		Telefone telefone = this.getTelefones(resultSet).get(0);
		preparedStatement.close();
		resultSet.close();
		return telefone;
	}

	@Override
	public void delete(Long id) throws ClassNotFoundException, SQLException,
			RegistroInexistenteException, IOException {
		if (this.getById(id) != null) {
			PreparedStatement preparedStatement = JDBCConnectionFactory
					.getInstance().getConnection()
					.prepareStatement(SQL_TELEFONE_DELETE);
			preparedStatement.setLong(1, id);
			preparedStatement.executeUpdate();
			preparedStatement.close();
		} else {
			throw new RegistroInexistenteException(
					TELEFONE_INEXISTENTE_EXCEPTION);
		}
	}

	@Override
	public List<Telefone> getByIdPessoa(long id) throws ClassNotFoundException,
			SQLException, IOException {
		PreparedStatement preparedStatement = JDBCConnectionFactory
				.getInstance().getConnection()
				.prepareStatement(SQL_TELEFONE_GET_BY_ID_PESSOA);
		preparedStatement.setLong(1, id);
		ResultSet resultSet = preparedStatement.executeQuery();
		List<Telefone> telefones = this.getTelefones(resultSet);
		preparedStatement.close();
		resultSet.close();
		return telefones;
	}

	@Override
	public List<TipoTelefone> getAllTipoTelefone()
			throws ClassNotFoundException, SQLException, IOException {
		List<TipoTelefone> tipoTelefones = new ArrayList<TipoTelefone>();
		PreparedStatement preparedStatement = JDBCConnectionFactory
				.getInstance().getConnection()
				.prepareStatement(SQL_TIPO_TELEFONE_GET_ALL);
		ResultSet resultSet = preparedStatement.executeQuery();
		Telefone telefone = new Telefone();
		while (resultSet.next()) {
			TipoTelefone tipoTelefone = telefone.new TipoTelefone(
					resultSet.getString("nome"));
			tipoTelefone.setId(resultSet.getLong("id"));
			tipoTelefones.add(tipoTelefone);
		}
		return tipoTelefones;
	}

	public Telefone getByPaisAreaNumero(int pais, int area, int numero)
			throws ClassNotFoundException, SQLException, IOException {
		PreparedStatement preparedStatement = JDBCConnectionFactory
				.getInstance().getConnection()
				.prepareStatement(SQL_TELEFONE_GET_BY_PAIS_AREA_NUMERO);
		preparedStatement.setInt(1, pais);
		preparedStatement.setInt(2, area);
		preparedStatement.setInt(3, numero);
		ResultSet resultSet = preparedStatement.executeQuery();
		Telefone telefone = this.getTelefones(resultSet).get(0);
		preparedStatement.close();
		resultSet.close();
		return telefone;
	}

	private List<Telefone> getTelefones(ResultSet resultSet)
			throws SQLException {
		List<Telefone> telefones = new ArrayList<Telefone>();
		while (resultSet.next()) {
			Telefone telefone = new Telefone();
			telefone.setId(resultSet.getLong("id"));
			telefone.setPais(resultSet.getInt("pais"));
			telefone.setArea(resultSet.getInt("area"));
			telefone.setNumero(resultSet.getInt("numero"));
			TipoTelefone tipoTelefone = telefone.new TipoTelefone(
					resultSet.getString("nome_tipotelefone"));
			tipoTelefone.setId(resultSet.getLong("id_tipotelefone"));
			telefone.setTipoTelefone(tipoTelefone);
			telefones.add(telefone);
		}
		return telefones;
	}

	private TipoTelefone getTipoTelefoneByName(String name)
			throws ClassNotFoundException, SQLException, IOException {
		TipoTelefone tipoTelefone = null;
		PreparedStatement preparedStatement = JDBCConnectionFactory
				.getInstance().getConnection()
				.prepareStatement(SQL_TIPO_TELEFONE_GET_BY_NAME);
		preparedStatement.setString(1, name);
		ResultSet resultSet = preparedStatement.executeQuery();
		Telefone telefone = new Telefone();
		if (resultSet.next()) {
			tipoTelefone = telefone.new TipoTelefone(
					resultSet.getString("nome"));
			tipoTelefone.setId(resultSet.getLong("id"));
		}
		preparedStatement.close();
		resultSet.close();
		return tipoTelefone;
	}

}
